home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / Xconq 7.1.0 / src / xconq-7.1.0 / mac / macimf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  25.2 KB  |  815 lines  |  [TEXT/R*ch]

  1. /* Image families for the Mac interface to Xconq.
  2.    Copyright (C) 1992, 1993, 1994, 1995 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. /* Note!  This file does not use the standard "conq.h" header, so can't assume
  10.    all the usual definitions. */
  11.  
  12. #include "config.h"
  13. #include "misc.h"
  14. #include "lisp.h"
  15. #include "imf.h"
  16.  
  17. #ifdef THINK_C
  18. #include <MacHeaders>
  19. #else /* assume MPW */
  20. #include <Types.h>
  21. #include <Memory.h>
  22. #include <Resources.h>
  23. #include <Quickdraw.h>
  24. #endif /* THINK_C */
  25.  
  26. #include "macimf.h"
  27.  
  28. extern int hasColorQD;
  29.  
  30. CTabHandle interp_ctab(Obj *palette);
  31. CTabHandle synth_ctab(void);
  32. void convert_ppat(Image *img, PixPatHandle colrpat);
  33. void convert_cicn(Image *img, CIconHandle colricon, int *hasmono, int *hasmask);
  34. Obj *convert_ctab(CTabHandle ctabhandle);
  35.  
  36. MacImage *
  37. init_mac_image(Image *img)
  38. {
  39.     int j;
  40.     MacImage *macimg;
  41.  
  42.     macimg = (MacImage *) xmalloc(sizeof(MacImage));
  43.     for (j = 0; j < 8; ++j)
  44.       SET_IMG_PAT (macimg, j, '\0');
  45.     macimg->generic = img;
  46.     return macimg;
  47. }
  48.  
  49. MacImage *
  50. get_mac_image(Image *img)
  51. {
  52.     MacImage *macimg;
  53.  
  54.     if (img->hook)
  55.       return (MacImage *) img->hook;
  56.     macimg = init_mac_image(img);
  57.     img->hook = (char *) macimg;
  58.     return macimg;
  59. }
  60.  
  61. /* This tries to fill in the given image family from various resources.  The order
  62.    should be "best first", so as to improve search time. */
  63.  
  64. void
  65. mac_load_imf(imf)
  66. ImageFamily *imf;
  67. {
  68.     int w, h, i, rsize, startlineno = 0, endlineno = 0;
  69.     char tmpstrbuf[100];
  70.     Obj *imfspec;
  71.     Image *img;
  72.     MacImage *macimg;
  73.     Handle imfhandle, pathandle, sicnhandle, iconhandle, maskhandle;
  74.     PicHandle pichandle;
  75.     PixPatHandle ppathandle;
  76.     PixMapHandle pmhandle;
  77.     CIconHandle cicnhandle;
  78.     PixMap pmap;
  79.     Rect bounds;
  80.     Str255 namestr, maskstr, im16x16str, resname;
  81.     short resid;
  82.     ResType restype;
  83.  
  84.     /* Can't do anything without a name for the image family. */
  85.     if (imf == NULL || imf->name == NULL)
  86.       return;
  87.     c2p(imf->name, namestr);
  88.     /* The name of the mask is always formed by appending " mask". */
  89.     sprintf(tmpstrbuf, "%s mask", imf->name);
  90.     c2p(tmpstrbuf, maskstr);
  91.     /* The name of the 16x16 cicn is always formed by appending " 16x16". */
  92.     sprintf(tmpstrbuf, "%s 16x16", imf->name);
  93.     c2p(tmpstrbuf, im16x16str);
  94.     /* Look for and load the image family specification resource first. */
  95.     imfhandle = (Handle) GetNamedResource('XCif', namestr);
  96.     if (imfhandle != nil) {
  97.         imfspec = read_form_from_string(copy_string(*imfhandle), &startlineno, &endlineno);
  98.         interp_imf_contents(imf, imfspec);
  99.     }
  100.     pichandle = (PicHandle) GetNamedResource('PICT', namestr);
  101.     if (pichandle != nil) {
  102.         img = get_img(imf, 16, 16); /* should get real bounds */
  103.         if (img != NULL) {
  104.             img->minw = img->minh = 8;
  105.             img->maxw = img->maxh = 9999;
  106.             macimg = get_mac_image(img);
  107.             /* (should distinguish mono and color picts somehow) */
  108.             macimg->monopict = pichandle;
  109.             /* Look for a mask too. */
  110.             pichandle = (PicHandle) GetNamedResource('PICT', maskstr);
  111.             if (pichandle != nil) {
  112.                 macimg->maskpict = pichandle;
  113.             }
  114.             img->istile = 0;
  115.         }
  116.     }
  117.     /* (should also be able to pick up picts with rows and columns of images, but
  118.         would need separate resource to identify which is which) */
  119.     /* Pick up cicns, if we can do color. */
  120.     if (hasColorQD) {
  121.         cicnhandle = (CIconHandle) GetNamedResource('cicn', namestr);
  122.         if (cicnhandle != nil) {
  123.             HLock((Handle) cicnhandle);
  124.             /* Need to get id so we can use special trap. */
  125.             GetResInfo((Handle) cicnhandle, &resid, &restype, resname);
  126.             cicnhandle = GetCIcon(resid);
  127.             pmap = (*cicnhandle)->iconPMap;
  128.             bounds = pmap.bounds;
  129.             w = bounds.right - bounds.left;  h = bounds.bottom - bounds.top;
  130.             img = get_img(imf, w, h);
  131.             if (img != NULL) {
  132.                 img->minw = img->minh = 8;
  133.                 img->maxw = img->maxh = 128;
  134.                 macimg = get_mac_image(img);
  135.                 macimg->colricon = (Handle) cicnhandle;
  136.                 /* Mask is built in, don't need to load separately. */
  137.             }
  138.             HUnlock((Handle) cicnhandle);
  139.         }
  140.         cicnhandle = (CIconHandle) GetNamedResource('cicn', im16x16str);
  141.         if (cicnhandle != nil) {
  142.             HLock((Handle) cicnhandle);
  143.             /* Need to get id so we can use special trap. */
  144.             GetResInfo((Handle) cicnhandle, &resid, &restype, resname);
  145.             cicnhandle = GetCIcon(resid);
  146.             pmap = (*cicnhandle)->iconPMap;
  147.             bounds = pmap.bounds;
  148.             w = bounds.right - bounds.left;  h = bounds.bottom - bounds.top;
  149.             img = get_img(imf, w, h);
  150.             if (img != NULL) {
  151.                 img->minw = img->minh = 8;
  152.                 img->maxw = img->maxh = 128;
  153.                 macimg = get_mac_image(img);
  154.                 macimg->colricon = (Handle) cicnhandle;
  155.                 /* Mask is built in, don't need to load separately. */
  156.             }
  157.             HUnlock((Handle) cicnhandle);
  158.         }
  159.     } else {
  160.         /* (should at least try to get the mono part, without using CQD traps) */
  161.     }
  162.     /* Pick up ICONs. */
  163.     iconhandle = (Handle) GetNamedResource('ICON', namestr);
  164.     if (iconhandle != nil) {
  165.         img = get_img(imf, 32, 32);
  166.         if (img != NULL) {
  167.             img->minw = img->minh = 8;
  168.             img->maxw = img->maxh = 128;
  169.             macimg = get_mac_image(img);
  170.             macimg->monoicon = iconhandle;
  171.             /* Look for a mask too. */
  172.             iconhandle = (Handle) GetNamedResource('ICON', maskstr);
  173.             if (iconhandle != nil) {
  174.                 macimg->maskicon = iconhandle;
  175.             }
  176.         }
  177.     }
  178.     /* Pick up SICNs. */
  179.     sicnhandle = (Handle) GetNamedResource('SICN', namestr);
  180.     if (sicnhandle != nil) {
  181.         img = get_img(imf, 16, 16);
  182.         if (img != NULL) {
  183.             img->minw = img->minh = 8;
  184.             img->maxw = img->maxh = 64;
  185.             macimg = get_mac_image(img);
  186.             /* Image itself is just the first 32 bytes, mask is second 32 if present. */
  187.             macimg->monosicn = sicnhandle;
  188.             rsize = SizeResource(sicnhandle);
  189.             if (rsize >= 64) {
  190.                 maskhandle = (Handle) NewHandle(32);
  191.                 for (i = 0; i < 32; ++i) {
  192.                     (*maskhandle)[i] = (*sicnhandle)[i+32];
  193.                 }
  194.                 macimg->masksicn = maskhandle;
  195.             } else {
  196.                 /* Mask could be separate resource, so look for it. */
  197.                 iconhandle = GetNamedResource('SICN', maskstr);
  198.                 if (iconhandle != nil) {
  199.                     macimg->masksicn = sicnhandle;
  200.                 } else {
  201.                     /* no mask to be found */
  202.                 }
  203.             }
  204.             img->istile = 0;
  205.         }
  206.     }
  207.     /* Pick up color patterns, if we're capable of doing color. */
  208.     if (hasColorQD) {
  209.         ppathandle = (PixPatHandle) GetNamedResource('ppat', namestr);
  210.         if (ppathandle != nil) {
  211.             /* Need to get the id of the ppat so we can use special trap. */
  212.             GetResInfo((Handle) ppathandle, &resid, &restype, resname);
  213.             ppathandle = GetPixPat(resid);
  214.             pmhandle = (*ppathandle)->patMap;
  215.             switch ((*ppathandle)->patType) {
  216.                 case 0:
  217.                     /* (should put something in monodata?) */
  218.                     w = h = 8;
  219.                     break;
  220.                 case 1:
  221.                     /* Compute the actual size of the pattern. */
  222.                     bounds = (*pmhandle)->bounds;
  223.                     w = bounds.right - bounds.left;  h = bounds.bottom - bounds.top;
  224.             }
  225.             img = get_img(imf, w, h);
  226.             if (img != NULL) {
  227.                 /* Indicate that we can use this pattern for any size area. */
  228.                 img->minw = img->minh = 1;
  229.                 img->maxw = img->maxh = 9999;
  230.                 img->istile = TRUE;
  231.                 macimg = get_mac_image(img);
  232.                 macimg->colrpat = ppathandle;
  233.                 if (w == 8 && h == 8) {
  234.                     /* Set the monopat. */
  235.                     for (i = 0; i < 8; ++i)
  236.                       SET_IMG_PAT(macimg, i, QD_PAT_ADDR((*ppathandle)->pat1Data)[i]);
  237.                     macimg->patdefined = 1;
  238.                 }
  239.             }
  240.             /* If the pattern is larger than 8x8, we need to make an 8x8 image for
  241.                the mono pattern. */
  242.             if (!(w == 8 && h == 8)) {
  243.                 img = get_img(imf, 8, 8);
  244.                 if (img != NULL) {
  245.                     /* Indicate that we can use this pattern for any size area. */
  246.                     img->minw = img->minh = 1;
  247.                     img->maxw = img->maxh = 9999;
  248.                     img->istile = TRUE;
  249.                     macimg = get_mac_image(img);
  250.                     /* Set the monopat. */
  251.                     for (i = 0; i < 8; ++i)
  252.                       SET_IMG_PAT(macimg, i, QD_PAT_ADDR((*ppathandle)->pat1Data)[i]);
  253.                     macimg->patdefined = 1;
  254.                 }
  255.             }
  256.         }
  257.     }
  258.     /* Load a pattern, which can be used for any size area, but whose "natural" size
  259.        is always 8x8. */
  260.     pathandle = GetNamedResource('PAT ', namestr);
  261.     if (pathandle != nil) {
  262.         img = get_img(imf, 8, 8);
  263.         if (img != NULL) {
  264.             img->minw = img->minh = 1;
  265.             img->maxw = img->maxh = 9999;
  266.             img->istile = TRUE;
  267.             macimg = get_mac_image(img);
  268.             if (macimg->patdefined) {
  269.                 int allzeros = TRUE;
  270.  
  271.                 for (i = 0; i < 8; ++i) {
  272.                     if (((char *) &(macimg->monopat))[i] != 0) {
  273.                         allzeros = FALSE;
  274.                         break;
  275.                     }
  276.                 }
  277.                 /* A mono pattern of all zeros is a default pat from a ppat; overwrite
  278.                    it silently. */
  279.                 if (!allzeros) {
  280.                     for (i = 0; i < 8; ++i) {
  281.                         if (((char *) &(macimg->monopat))[i] != ((char *) *pathandle)[i]) {
  282.                             run_warning("ppat/PAT mismatch for \"%s\", overwriting ppat",
  283.                                         imf->name);
  284.                             break;
  285.                         }
  286.                     }
  287.                 }
  288.                 for (i = 0; i < 8; ++i)
  289.                   SET_IMG_PAT(macimg, i, ((char *) *pathandle)[i]);
  290.             } else {
  291.                 /* Set the monopat. */
  292.                 for (i = 0; i < 8; ++i)
  293.                   SET_IMG_PAT(macimg, i, ((char *) *pathandle)[i]);
  294.                 macimg->patdefined = 1;
  295.             }
  296.         }
  297.     }
  298. }
  299.  
  300. /* Given an image family that already has data for it, in Lisp form,
  301.    make platform-specific images. */
  302.  
  303. void
  304. mac_interp_imf(imf)
  305. ImageFamily *imf;
  306. {
  307.     int w, h, i, numbytes, bitrowbytes, actualw, actualh, pixelsize, rowbytes;
  308.     int monodone, colrdone, maskdone;
  309.     Image *img;
  310.     MacImage *macimg;
  311.     Handle sicnhandle, iconhandle, datahandle;
  312.     Handle monohandle = nil, maskhandle = nil;
  313.     PixPatHandle ppathandle;
  314.     CIconHandle cicnhandle;
  315.     PixMapHandle pmhandle;
  316.  
  317.     for (img = imf->images; img != NULL; img = img->next) {
  318.         w = img->w;  h = img->h;
  319.         actualw = img->actualw;  actualh = img->actualh;
  320.         pixelsize = img->pixelsize;
  321.         rowbytes = img->rowbytes;
  322.         macimg = get_mac_image(img);
  323.         /* Mono icons and masks are very similar; digest both here. */
  324.         monodone = colrdone = maskdone = FALSE;
  325.         if (w == 8 && h == 8 && img->monodata != lispnil && img->istile) {
  326.             /* Monochrome pattern. */
  327.             datahandle = NewHandle(8);
  328.             memset(*datahandle, 0, 8);
  329.             /* Read exactly 8 bytes. */
  330.             mac_interp_bytes(img->monodata, 8, datahandle, 0);
  331.             /* Fill in the monopat. */
  332.             for (i = 0; i < 8; ++i)
  333.               SET_IMG_PAT(macimg, i, (*datahandle)[i]);
  334.             macimg->patdefined = TRUE;
  335.             /* Patterns have no masks, but defeat subsequent mask hacking. */
  336.             monodone = maskdone = TRUE;
  337.         }
  338.         if (w == 16 && h == 16 && img->monodata != lispnil) {
  339.             /* Shape is appropriate for a small icon, make one. */
  340.             sicnhandle = NewHandle(32);
  341.             memset(*sicnhandle, 0, 32);
  342.             /* Read exactly 32 bytes. */
  343.             mac_interp_bytes(img->monodata, 32, sicnhandle, 0);
  344.             macimg->monosicn = sicnhandle;
  345.             monodone = TRUE;
  346.         }
  347.         if (w == 16 && h == 16 && img->maskdata != lispnil) {
  348.             /* Shape is appropriate for a small icon mask, make one. */
  349.             sicnhandle = NewHandle(32);
  350.             memset(*sicnhandle, 0, 32);
  351.             /* Read exactly 32 bytes. */
  352.             mac_interp_bytes(img->maskdata, 32, sicnhandle, 0);
  353.             macimg->masksicn = sicnhandle;
  354.             maskdone = TRUE;
  355.         }
  356.         if (w == 32 && h == 32 && img->monodata != lispnil) {
  357.             /* Shape is appropriate for a standard icon, make one. */
  358.             iconhandle = NewHandle(128);
  359.             memset(*iconhandle, 0, 128);
  360.             /* Read exactly 128 bytes. */
  361.             mac_interp_bytes(img->monodata, 128, iconhandle, 0);
  362.             macimg->monoicon = iconhandle;
  363.             monodone = TRUE;
  364.         }
  365.         if (w == 32 && h == 32 && img->maskdata != lispnil) {
  366.             /* Shape is appropriate for a standard icon, make one. */
  367.             iconhandle = NewHandle(128);
  368.             memset(*iconhandle, 0, 128);
  369.             /* Read exactly 128 bytes. */
  370.             mac_interp_bytes(img->maskdata, 128, iconhandle, 0);
  371.             macimg->maskicon = iconhandle;
  372.             maskdone = TRUE;
  373.         }
  374.         /* The mono and mask data are probably going to go into the cicn - save them
  375.            into a handle for now. */
  376.         if (!monodone && img->monodata != lispnil) {
  377.             if (rowbytes < 1)
  378.               rowbytes = ((actualw + 15) / 16) * 2;
  379.             numbytes = actualh * (actualw <= 8 ? 2 : rowbytes);
  380.             monohandle = NewHandle(numbytes);
  381.             memset(*maskhandle, 0, numbytes);
  382.             /* Read as many bytes as directed. */
  383.             mac_interp_bytes(img->monodata, numbytes, monohandle, (actualw <= 8 ? 1 : 0));
  384.             monodone = TRUE;
  385.         }
  386.         if (!maskdone && img->maskdata != lispnil) {
  387.             if (rowbytes < 1)
  388.               rowbytes = ((actualw + 15) / 16) * 2;
  389.             numbytes = actualh * (actualw <= 8 ? 2 : rowbytes);
  390.             maskhandle = NewHandle(numbytes);
  391.             memset(*maskhandle, 0, numbytes);
  392.             /* Read as many bytes as directed. */
  393.             mac_interp_bytes(img->maskdata, numbytes, maskhandle, (actualw <= 8 ? 1 : 0));
  394.             maskdone = TRUE;
  395.         }
  396.         /* Limit bits per pixel to reasonable values. */
  397.         if (pixelsize < 1 || pixelsize > 8)
  398.           pixelsize = 8;
  399.         /* A sufficiently small tiling color image can be a color pattern. */
  400.         if (hasColorQD && actualw <= 64 && actualh <= 64 && img->istile && img->colrdata != lispnil) {
  401.             /* Make a color pattern. */
  402.             ppathandle = NewPixPat();
  403.             pmhandle = (*ppathandle)->patMap;
  404.             SetRect(&((*pmhandle)->bounds), 0, 0, actualw, actualh);
  405.             if (rowbytes < 1)
  406.               rowbytes = (actualw * pixelsize) / 8;
  407.             (*pmhandle)->rowBytes = rowbytes;
  408.             (*pmhandle)->pixelSize = pixelsize;
  409.             (*pmhandle)->pmTable = interp_ctab(img->palette);
  410.             numbytes = actualh * rowbytes;
  411.             datahandle = NewHandle(numbytes);
  412.             (*ppathandle)->patData = datahandle;
  413.             mac_interp_bytes(img->colrdata, numbytes, datahandle, 0);
  414.             (*ppathandle)->patXValid = -1;
  415.             macimg->colrpat = ppathandle;
  416.             colrdone = maskdone = TRUE;
  417.         }
  418.         if (hasColorQD && actualw <= 64 && actualh <= 64
  419.             && !img->istile
  420.             && (img->colrdata != lispnil
  421.                 || (macimg->monosicn == nil
  422.                     && macimg->masksicn == nil
  423.                     && macimg->monoicon == nil
  424.                     && macimg->maskicon == nil
  425.                    ))) {
  426.             /* If no color data in evidence, prepare to use mono or mask instead. */
  427.             if (img->colrdata == lispnil) {
  428.                 pixelsize = 1;
  429.             }
  430.             /* Make a full color icon. */
  431.             bitrowbytes = ((actualw + 15) / 16) * 2;
  432.             /* Allocate enough space for the icon and its data/mask bitmaps. */
  433.             cicnhandle = (CIconHandle) NewHandle(sizeof(CIcon) + 2 * actualh * bitrowbytes);
  434.             HLock((Handle) cicnhandle);
  435.             (*cicnhandle)->iconPMap.baseAddr = 0;
  436.             if (rowbytes < 1)
  437.               rowbytes = ((actualw + 15) / 16) * pixelsize * 2;
  438.             (*cicnhandle)->iconPMap.rowBytes = rowbytes | 0x8000;
  439.             SetRect(&((*cicnhandle)->iconPMap.bounds), 0, 0, actualw, actualh);
  440.             (*cicnhandle)->iconPMap.pmVersion = 0;
  441.             (*cicnhandle)->iconPMap.packType = 0;
  442.             (*cicnhandle)->iconPMap.packSize = 0;
  443.             (*cicnhandle)->iconPMap.hRes = 0;
  444.             (*cicnhandle)->iconPMap.vRes = 0;
  445.             (*cicnhandle)->iconPMap.pixelType = 0;
  446.             (*cicnhandle)->iconPMap.pixelSize = pixelsize;
  447.             (*cicnhandle)->iconPMap.cmpCount = 1;
  448.             (*cicnhandle)->iconPMap.cmpSize = pixelsize;
  449.             (*cicnhandle)->iconPMap.planeBytes = 0;
  450.             (*cicnhandle)->iconPMap.pmTable = interp_ctab(img->palette);
  451.             (*cicnhandle)->iconPMap.pmReserved = 0;
  452.             /* Configure the monochrome icon. */
  453.             SetRect(&((*cicnhandle)->iconBMap.bounds), 0, 0, actualw, actualh);
  454.             (*cicnhandle)->iconBMap.rowBytes = 0;
  455.             (*cicnhandle)->iconBMap.baseAddr = NULL;
  456.             SetRect(&((*cicnhandle)->iconMask.bounds), 0, 0, actualw, actualh);
  457.             /* Configure the mask bitmap. */
  458.             (*cicnhandle)->iconMask.rowBytes = bitrowbytes;
  459.             (*cicnhandle)->iconMask.baseAddr = NULL;
  460.             numbytes = actualh * rowbytes;
  461.             datahandle = NewHandle(numbytes);
  462.             (*cicnhandle)->iconData = datahandle;
  463.             /* Fill up the datahandle with the color data, or else use mono/mask data
  464.                if the color data is missing. */
  465.             if (img->colrdata != lispnil) {
  466.                 mac_interp_bytes(img->colrdata, numbytes, datahandle, 0);
  467.             } else if (img->monodata != lispnil) {
  468.                 mac_interp_bytes(img->monodata, numbytes, datahandle, (actualw <= 8 ? 1 : 0));
  469.                 /* We need an ersatz color table. */
  470.                 (*cicnhandle)->iconPMap.pmTable = synth_ctab();
  471.             } else if (img->maskdata != lispnil) {
  472.                 mac_interp_bytes(img->maskdata, numbytes, datahandle, (actualw <= 8 ? 1 : 0));
  473.                 /* We need an ersatz color table. */
  474.                 (*cicnhandle)->iconPMap.pmTable = synth_ctab();
  475.             }
  476.             /* If a mono icon is already set up, use it as the icon's bitmap. */
  477.             if (macimg->monoicon != nil) {
  478.                 HLock(macimg->monoicon);
  479.                 memcpy(((char *) (*cicnhandle)->iconMaskData) + actualh * bitrowbytes,
  480.                        *(macimg->monoicon), actualh * bitrowbytes);
  481.                 (*cicnhandle)->iconBMap.rowBytes = bitrowbytes;
  482.                 HUnlock(macimg->monoicon);
  483.             }
  484.             /* If a mono sicn is already set up, use it as the icon's bitmap. */
  485.             if (macimg->monosicn != nil) {
  486.                 HLock(macimg->monosicn);
  487.                 memcpy(((char *) (*cicnhandle)->iconMaskData) + actualh * bitrowbytes,
  488.                        *(macimg->monosicn), actualh * bitrowbytes);
  489.                 (*cicnhandle)->iconBMap.rowBytes = bitrowbytes;
  490.                 HUnlock(macimg->monosicn);
  491.             }
  492.             /* ...or just use the monohandle that we built earlier. */
  493.             if (monohandle != nil) {
  494.                 HLock(monohandle);
  495.                 memcpy(((char *) (*cicnhandle)->iconMaskData) + actualh * bitrowbytes,
  496.                        *monohandle, actualh * bitrowbytes);
  497.                 (*cicnhandle)->iconBMap.rowBytes = bitrowbytes;
  498.                 HUnlock(monohandle);
  499.             }
  500.             /* If a mask icon is already set up, use it as the icon's mask. */
  501.             if (macimg->maskicon != nil) {
  502.                 HLock(macimg->maskicon);
  503.                 memcpy((char *) (*cicnhandle)->iconMaskData,
  504.                        *(macimg->maskicon), actualh * bitrowbytes);
  505.                 HUnlock(macimg->maskicon);
  506.             }
  507.             /* If a mask sicn is already set up, use it as the icon's mask. */
  508.             if (macimg->masksicn != nil) {
  509.                 HLock(macimg->masksicn);
  510.                 memcpy((char *) (*cicnhandle)->iconMaskData,
  511.                        *(macimg->masksicn), actualh * bitrowbytes);
  512.                 HUnlock(macimg->masksicn);
  513.             }
  514.             /* ...or just use the maskhandle that we built earlier. */
  515.             if (maskhandle != nil) {
  516.                 HLock(maskhandle);
  517.                 memcpy((char *) (*cicnhandle)->iconMaskData,
  518.                        *maskhandle, actualh * bitrowbytes);
  519.                 HUnlock(maskhandle);
  520.             }
  521.             macimg->colricon = (Handle) cicnhandle;
  522.             HUnlock((Handle) cicnhandle);
  523.             colrdone = TRUE;
  524.         }
  525.         if (!monodone && !colrdone) {
  526.             run_warning("%dx%d image of \"%s\" could not be interpreted", w, h, imf->name);
  527.         }
  528.     }
  529. #if 0 /* broken */
  530.     /* If we have a color pattern of random size, and an 8x8 mono pattern, then we should
  531.        glue the mono pattern into the color pattern's mono slot.  This requires searching
  532.        all pairs of images in the family. */
  533.     for (img = imf->images; img != NULL; img = img->next) {
  534.         Image *img2;
  535.         MacImage *macimg2;
  536.         macimg = get_mac_image(img);
  537.         if (macimg->colrpat != nil) {
  538.             for (img2 = imf->images; img2 != NULL; img2 = img2->next) {
  539.                 macimg2 = get_mac_image(img2);
  540.                 if (macimg2->patdefined) {
  541.                     memcpy((char *) &(*(macimg->colrpat)->pat1Data), (char *) &(macimg2->monopat), 8);
  542.                 }
  543.             }
  544.         }
  545.     }
  546. #endif
  547. }
  548.  
  549. void
  550. mac_interp_bytes(datalist, numbytes, desthandle, jump)
  551. Obj *datalist;
  552. int numbytes, jump;
  553. Handle desthandle;
  554. {
  555.     HLock(desthandle);
  556.     interp_bytes(datalist, numbytes, *desthandle, jump);
  557.     HUnlock(desthandle);
  558. }
  559.  
  560. /* Given a list of color table entries, create and return a color table. */
  561.  
  562. CTabHandle
  563. interp_ctab(palette)
  564. Obj *palette;
  565. {
  566.     int len, i;
  567.     Obj *head, *rest, *color;
  568.     ColorSpec *ctdata;
  569.     CTabHandle ctabhandle;
  570.  
  571.     len = length(palette);
  572.     if (len == 0)
  573.       return nil;
  574.     ctabhandle = (CTabHandle) NewHandle(8 + len * 8);
  575.     HLock((Handle) ctabhandle);
  576.     (*ctabhandle)->ctFlags = 0;
  577.     (*ctabhandle)->ctSeed = GetCTSeed();
  578.     (*ctabhandle)->ctSize = len - 1;
  579.     ctdata = (ColorSpec *) &((*ctabhandle)->ctTable);
  580.     for (i = 0, rest = palette; i < len; ++i, rest = cdr(rest)) {
  581.         head = car(rest);
  582.         ctdata[i].value = c_number(car(head));
  583.         color = cdr(head);
  584.         ctdata[i].rgb.red = c_number(car(color));
  585.         ctdata[i].rgb.green = c_number(cadr(color));
  586.         ctdata[i].rgb.blue = c_number(car(cddr(color)));
  587.     }
  588.     HUnlock((Handle) ctabhandle);
  589.     return ctabhandle;
  590. }
  591.  
  592. CTabHandle
  593. synth_ctab()
  594. {
  595.     int len;
  596.     ColorSpec *ctdata;
  597.     CTabHandle ctabhandle;
  598.  
  599.     len = 2;
  600.     ctabhandle = (CTabHandle) NewHandle(8 + len * 8);
  601.     HLock((Handle) ctabhandle);
  602.     (*ctabhandle)->ctFlags = 0;
  603.     (*ctabhandle)->ctSeed = GetCTSeed();
  604.     (*ctabhandle)->ctSize = len - 1;
  605.     ctdata = (ColorSpec *) &((*ctabhandle)->ctTable);
  606.     ctdata[0].value = 0;
  607.     ctdata[0].rgb.red = 65535;
  608.     ctdata[0].rgb.green = 65535;
  609.     ctdata[0].rgb.blue = 65535;
  610.     ctdata[1].value = 1;
  611.     ctdata[1].rgb.red = 0;
  612.     ctdata[1].rgb.green = 0;
  613.     ctdata[1].rgb.blue = 0;
  614.     HUnlock((Handle) ctabhandle);
  615.     return ctabhandle;
  616. }
  617.  
  618. void
  619. make_generic_image_data(ImageFamily *imf)
  620. {
  621.     int i, hasmono, hasmask;
  622.     Image *img;
  623.     MacImage *macimg;
  624.  
  625.     for (img = imf->images; img != NULL; img = img->next) {
  626.         hasmono = hasmask = FALSE;
  627.         macimg = get_mac_image(img);
  628.         if (hasColorQD && macimg->colricon != nil) {
  629.             convert_cicn(img, (CIconHandle) macimg->colricon, &hasmono, &hasmask);
  630.         }
  631.         if (hasColorQD && macimg->colrpat != nil) {
  632.             convert_ppat(img, macimg->colrpat);
  633.         }
  634.         if (macimg->monoicon != nil && !hasmono) {
  635.             img->rawmonodata = xmalloc(128);
  636.             for (i = 0; i < 128; ++i)
  637.               img->rawmonodata[i] = ((char *) *(macimg->monoicon))[i];
  638.         }
  639.         if (macimg->maskicon != nil && !hasmask) {
  640.             img->rawmaskdata = xmalloc(128);
  641.             for (i = 0; i < 128; ++i)
  642.               img->rawmaskdata[i] = ((char *) *(macimg->maskicon))[i];
  643.         }
  644.         if (macimg->monosicn != nil && !hasmono) {
  645.             img->rawmonodata = xmalloc(32);
  646.             for (i = 0; i < 32; ++i)
  647.               img->rawmonodata[i] = ((char *) *(macimg->monosicn))[i];
  648.         }
  649.         if (macimg->masksicn != nil && !hasmask) {
  650.             img->rawmaskdata = xmalloc(32);
  651.             for (i = 0; i < 32; ++i)
  652.               img->rawmaskdata[i] = ((char *) *(macimg->masksicn))[i];
  653.         }
  654.         if (macimg->patdefined) {
  655.             img->rawmonodata = xmalloc(8);
  656.             for (i = 0; i < 8; ++i)
  657.               img->rawmonodata[i] = ((char *) &(macimg->monopat))[i];
  658.         }
  659.     }
  660. }
  661.  
  662. /* Generify a color pattern. */
  663.  
  664. void
  665. convert_ppat(Image *img, PixPatHandle pat)
  666. {
  667.     int w, h, i, numbytes;
  668.     Rect bounds;
  669.     PixMapHandle pmhandle = (*pat)->patMap;
  670.     CTabHandle ctabhandle = (*pmhandle)->pmTable;
  671.     Handle patdata = (*pat)->patData;
  672.  
  673.     switch ((*pat)->patType) {
  674.         case 0:
  675.             /* (should put something in monodata?) */
  676.             break;
  677.         case 1:
  678.             /* Compute the actual size of the pattern. */
  679.             bounds = (*pmhandle)->bounds;
  680.             w = bounds.right - bounds.left;  h = bounds.bottom - bounds.top;
  681.             if (w != img->w || h != img->h) {
  682.                 img->actualw = w;  img->actualh = h;
  683.             }
  684.             img->rowbytes = (*pmhandle)->rowBytes & 0x3fff;
  685.             img->pixelsize = (*pmhandle)->pixelSize;
  686.             img->palette = convert_ctab(ctabhandle);
  687.             numbytes = h * img->rowbytes;
  688.             img->rawcolrdata = xmalloc(numbytes);
  689.             for (i = 0; i < numbytes; ++i)
  690.               img->rawcolrdata[i] = (*patdata)[i];
  691.             break;
  692.         case 2:
  693.             run_warning("Type 2 (RGB) pattern, ignoring");
  694.             break;
  695.     }
  696. }
  697.  
  698. /* Generify the data in a color icon. */
  699.  
  700. void
  701. convert_cicn(Image *img, CIconHandle cicnhandle, int *hasmono, int *hasmask)
  702. {
  703.     int w, h, i, rowbytes, numbytes;
  704.     Rect bounds;
  705.     char *baseaddr;
  706.     PixMap pmap = (*cicnhandle)->iconPMap;
  707.     CTabHandle ctabhandle = pmap.pmTable;
  708.     Handle datahandle;
  709.  
  710.     *hasmono = *hasmask = FALSE;
  711.     HLock((Handle) cicnhandle);
  712.     bounds = pmap.bounds;
  713.     w = bounds.right - bounds.left;  h = bounds.bottom - bounds.top;
  714.     if (w != img->w || h != img->h) {
  715.         img->actualw = w;  img->actualh = h;
  716.     }
  717.     img->rowbytes = pmap.rowBytes & 0x3fff;
  718.     img->pixelsize = pmap.pixelSize;
  719.     img->palette = convert_ctab(ctabhandle);
  720.     numbytes = h * img->rowbytes;
  721.     img->rawcolrdata = xmalloc(numbytes);
  722.     datahandle = (*cicnhandle)->iconData;
  723.     for (i = 0; i < numbytes; ++i)
  724.       img->rawcolrdata[i] = (*datahandle)[i];
  725.     /* Convert the cicn's monochrome icon if defined. */
  726.     rowbytes = (*cicnhandle)->iconBMap.rowBytes;
  727.     if (rowbytes > 0) {
  728.         baseaddr = ((char *) (*cicnhandle)->iconMaskData) + h * rowbytes;
  729.         numbytes = h * rowbytes;
  730.         img->rawmonodata = xmalloc(numbytes);
  731.         for (i = 0; i < numbytes; ++i) {
  732.             img->rawmonodata[i] = baseaddr[i];
  733.             /* For small icons, jump over a not-strictly-necessary padding char. */
  734.             if (w <= 8 && rowbytes == 2) ++i;
  735.         }
  736.         *hasmono = TRUE;
  737.     }
  738.     /* Write the cicn's mask if one is defined. */
  739.     rowbytes = (*cicnhandle)->iconMask.rowBytes;
  740.     if (rowbytes > 0) {
  741.         baseaddr = (char *) (*cicnhandle)->iconMaskData;
  742.         numbytes = h * rowbytes;
  743.         img->rawmaskdata = xmalloc(numbytes);
  744.         for (i = 0; i < numbytes; ++i) {
  745.             img->rawmaskdata[i] = baseaddr[i];
  746.             /* For small icons, jump over a not-strictly-necessary padding char. */
  747.             if (w <= 8 && rowbytes == 2) ++i;
  748.         }
  749.         *hasmask = TRUE;
  750.     }
  751.     HUnlock((Handle) cicnhandle);
  752. }
  753.  
  754. /* Write a color table. */
  755.  
  756. Obj *
  757. convert_ctab(CTabHandle ctabhandle)
  758. {
  759.     int c, ctsize;
  760.     ColorSpec cspec;
  761.     Obj *rslt = lispnil, *tmp, *rest, *restprev, *tmp2;
  762.  
  763.     if (ctabhandle == nil)
  764.       return lispnil;
  765.     ctsize = (*ctabhandle)->ctSize;
  766.     if (ctsize >= 0) {
  767.         HLock((Handle) ctabhandle);
  768.         for (c = 0; c <= ctsize; ++c) {
  769.             cspec = (*ctabhandle)->ctTable[c];
  770.             tmp = cons(new_number(cspec.value),
  771.                        cons(new_number(cspec.rgb.red),
  772.                                cons(new_number(cspec.rgb.green),
  773.                                     cons(new_number(cspec.rgb.blue),
  774.                                           lispnil))));
  775.             /* Splice the new entry into the list so that all are sorted by index. */
  776.             restprev = lispnil;
  777.             for (rest = rslt;
  778.                  cspec.value > (numberp(car(car(rest))) ? c_number(car(car(rest))) : 1000000);
  779.                  rest = cdr(rest)) {
  780.                 restprev = rest;
  781.             }
  782.             tmp2 = cons(tmp, rest);
  783.             if (restprev != lispnil)
  784.               set_cdr(restprev, tmp2);
  785.             else
  786.               rslt = tmp2;
  787.         }
  788.         HUnlock((Handle) ctabhandle);
  789.     }
  790.     return rslt;
  791. }
  792.  
  793. void
  794. mac_load_image_color(imc)
  795. ImageColor *imc;
  796. {
  797.     Handle imchandle;
  798.     Str255 namestr;
  799.  
  800.     if (imc->name == NULL)
  801.       return;
  802.     c2p(imc->name, namestr);
  803.     imchandle = GetNamedResource('XCic', namestr);
  804.     if (imchandle != nil) {
  805.         imc->r = ((short *) (*imchandle))[0];
  806.         imc->g = ((short *) (*imchandle))[1];
  807.         imc->b = ((short *) (*imchandle))[2];
  808.         imc->defined = 1;
  809.     } else {
  810.         /* Not found. */
  811.         imc->r = imc->g = imc->b = 0;
  812.         imc->defined = 0;
  813.     }
  814. }
  815.